package com.qigao.mall.service.impl;

import com.qigao.mall.api.AccountInfoService;
import com.qigao.mall.api.AccountSerivce;
import com.qigao.mall.commons.dto.AccountAmtOperDto;
import com.qigao.mall.commons.dto.AccountOperDto;
import com.qigao.mall.commons.dto.AccountTradeDto;
import com.qigao.mall.commons.enums.*;
import com.qigao.mall.commons.utils.IDUtils;
import com.qigao.mall.jdbc.mapper.TbAccountInfoMapper;
import com.qigao.mall.jdbc.mapper.TbAccountLogMapper;
import com.qigao.mall.jdbc.mapper.TbAccountTradeMapper;
import com.qigao.mall.jdbc.model.TbAccountInfo;
import com.qigao.mall.jdbc.model.TbAccountLog;
import com.qigao.mall.jdbc.model.TbAccountTrade;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @author luiz
 * @Title: com.qigao.mall.service.impl
 * @ProjectName three-mall
 * @date 2020-03-2020/3/27 15:10
 * @Description:
 */
@Service
@Slf4j
public class AccountServiceImpl implements AccountSerivce {
    @Resource
    private TbAccountInfoMapper tbAccountInfoMapper;
    @Resource
    private AccountInfoService accountInfoService;
    @Resource
    private TbAccountTradeMapper tbAccountTradeMapper;
    @Resource
    private TbAccountLogMapper tbAccountLogMapper;
    @Override
    public Result checkBalance(String ownerNo, String accountType,BigDecimal subAmt) {
        TbAccountInfo tbAccountInfo=tbAccountInfoMapper.selectByOwnerNoAndAccountType(ownerNo, accountType);
        if(tbAccountInfo==null) {
            return Result.newError(ResultCode.ACCOUNT_NOT_EXISTS);
        }
        BigDecimal accountAmt=tbAccountInfo.getAccountAmt();
        if(accountAmt.compareTo(subAmt)==-1){
            log.warn("{},{}账户余额{}不足扣减{}",ownerNo,accountType,accountAmt,subAmt);
           return Result.newError(ResultCode.ACCOUNT_AMT_ERROR);
        }
        return Result.newSuccess(tbAccountInfo);

    }

   /* @Override
    public Result checkBalance(String accountNo,BigDecimal subAmt) {
        TbAccountInfo tbAccountInfo=tbAccountInfoMapper.selectByAccountNo(accountNo);
        if(tbAccountInfo==null) {
            return Result.newError(ResultCode.ACCOUNT_NOT_EXISTS);
        }
        BigDecimal accountAmt=tbAccountInfo.getAccountAmt();
        if(accountAmt.compareTo(subAmt)==-1){
            log.warn("{}账户余额{}不足扣减{}",accountNo,accountAmt,subAmt);
            return Result.newError(ResultCode.ACCOUNT_AMT_ERROR);
        }
        return Result.newSuccess(tbAccountInfo);
    }

    *//**
     * 付款、退款交易操作
     * @param accountOperDto
     *//*
    @Override
    public boolean trade(AccountOperDto accountOperDto) {
        //1.账户校验
        AccountTradeDto accountTradeDto=accountValid(accountOperDto);
        //2.记录交易日志（复式记账）
        int tradeNum = insertAccountTrade(accountTradeDto);
        //3.记录账户日志（单边账）
        int logNum =insertAccountLog(accountTradeDto);
        //4.增加收款方账户余额
        int accountNum =operAccountAmt(accountTradeDto);
        if(tradeNum!=1 || logNum!=2 ||accountNum!=1){
            return false;
        }
        return true;
    }

    *//**
     * 单方面减少账户余额
     * @return
     *//*
    @Override
    public boolean subOrAddAccount(AccountOperDto accountOperDto) {
        //1.账户校验
        AccountTradeDto accountTradeDto=accountFromValid(accountOperDto);
        //2.记录账户日志（单边账）
        int logNum = insertFromtAccountLog(accountTradeDto);
        //3.增加或减少收款方账户余额
        int accountNum =operAccountAmt(accountTradeDto);
        if(logNum!=2 ||accountNum!=1){
            return false;
        }
        return true;
    }*/

    @Override
    public boolean operAccountAmt(AccountAmtOperDto accountAmtOperDto) {
        //金额为0 不记录
        if(BigDecimal.ZERO.compareTo(accountAmtOperDto.getTradeAmt())==0)return true;
        TbAccountInfo tbAccountInfo=tbAccountInfoMapper.selectByAccountNo(accountAmtOperDto.getAccoutNo());
        if(tbAccountInfo==null)return true;
        //2.记录账户日志（单边账）
        int logNum = insertAccountLog(tbAccountInfo,accountAmtOperDto);
        //3.增加或减少收款方账户余额
        int accountNum =addAccountAmt(accountAmtOperDto,tbAccountInfo);
        if(logNum!=1 ||accountNum!=1){
            return false;
        }
        return true;
    }


    /**
     * 操作商户端账户余额
     */
    private int addAccountAmt(AccountAmtOperDto accountAmtOperDto,TbAccountInfo tbAccountInfo) {
        tbAccountInfo.setAccountAmt(accountAmtOperDto.getTradeAmt());
        return tbAccountInfoMapper.addAmt(tbAccountInfo);
    }

    private int insertAccountLog(TbAccountInfo tbAccountInfo, AccountAmtOperDto accountAmtOperDto) {
        TbAccountLog toAccountLog=new TbAccountLog();
        toAccountLog.setLogNo(IDUtils.genIdStr(IdTypeEnum.RADOM));
        toAccountLog.setAccountNo(tbAccountInfo.getAccountNo());
        toAccountLog.setAccountName(tbAccountInfo.getAccountName());
        TradeTypeEnum tradeTypeEnum=accountAmtOperDto.getSourceTradeType();
        toAccountLog.setAmtDirect(tradeTypeEnum.getAmtDirect());
        toAccountLog.setOperAmt(accountAmtOperDto.getTradeAmt());
        toAccountLog.setOperAction(accountAmtOperDto.getSourceTradeType().name());
        toAccountLog.setOperName(accountAmtOperDto.getSourceTradeType().getName());
        toAccountLog.setUserNo(tbAccountInfo.getOwnerNo());
        toAccountLog.setUserName(tbAccountInfo.getOwnerName());
        toAccountLog.setCompNo(tbAccountInfo.getCompNo());
        toAccountLog.setCompName(tbAccountInfo.getCompName());
        toAccountLog.setSourceOrderNo(accountAmtOperDto.getSourceOrderNo());
        toAccountLog.setSourceOrderType(accountAmtOperDto.getSourceTradeType().name());
        toAccountLog.setCreateTime(new Date());
        return tbAccountLogMapper.insertSelective(toAccountLog);
    }


    /**
     * 记录账户交易日志
     * @param accountTradeDto
     */
   /* private int insertAccountTrade(AccountTradeDto accountTradeDto) {
        TbAccountTrade tbAccountTrade=new TbAccountTrade();
        BeanUtils.copyProperties(accountTradeDto,tbAccountTrade);
        tbAccountTrade.setTradeNo(IDUtils.genIdStr(IdTypeEnum.TRADE));
        tbAccountTrade.setOperAmt(accountTradeDto.getOperAmt());
        tbAccountTrade.setCreateTime(new Date());
        tbAccountTrade.setModiTime(new Date());
        return tbAccountTradeMapper.insertSelective(tbAccountTrade);
    }
    private int insertAccountLog(AccountTradeDto accountTradeDto) {
       int insertNum1 = insertFromtAccountLog(accountTradeDto);
       int insertNum2 =insertToAccountLog(accountTradeDto);
       return insertNum1+insertNum2;
    }*/

   /* private int insertToAccountLog(AccountTradeDto accountTradeDto) {
        TbAccountLog toAccountLog=new TbAccountLog();
        toAccountLog.setLogNo(IDUtils.genIdStr(IdTypeEnum.RADOM));
        toAccountLog.setAccountNo(accountTradeDto.getToAccountNo());
        toAccountLog.setAccountName(accountTradeDto.getToAccountName());
        TradeTypeEnum tradeTypeEnum=accountTradeDto.getSourceTradeType();
       // toAccountLog.setAmtDirect(tradeTypeEnum.getAmtDirect());
        toAccountLog.setOperAmt(accountTradeDto.getOperAmt());
        toAccountLog.setOperAction(accountTradeDto.getOperAction());
        toAccountLog.setOperName(accountTradeDto.getOperName());
        toAccountLog.setUserNo(accountTradeDto.getUserNo());
        toAccountLog.setUserName(accountTradeDto.getUserName());
        toAccountLog.setMerNo(accountTradeDto.getMerNo());
        toAccountLog.setMerName(accountTradeDto.getMerName());
        toAccountLog.setSourceOrderNo(accountTradeDto.getSourceOrderNo());
        toAccountLog.setSourceOrderType(accountTradeDto.getSourceOrderType());
        toAccountLog.setCreateTime(new Date());
        return tbAccountLogMapper.insertSelective(toAccountLog);
    }

    private int insertFromtAccountLog(AccountTradeDto accountTradeDto) {
        TbAccountLog fromAccountLog=new TbAccountLog();
        fromAccountLog.setLogNo(IDUtils.genIdStr(IdTypeEnum.RADOM));
        fromAccountLog.setAccountNo(accountTradeDto.getFromAccountNo());
        fromAccountLog.setAccountName(accountTradeDto.getFromAccountName());
        TradeTypeEnum tradeTypeEnum=accountTradeDto.getSourceTradeType();
        fromAccountLog.setAmtDirect(AmtDirectEnum.ADD.getCode());
        fromAccountLog.setOperAmt(accountTradeDto.getOperAmt());
        fromAccountLog.setOperAction(accountTradeDto.getOperAction());
        fromAccountLog.setOperName(accountTradeDto.getOperName());
        fromAccountLog.setUserNo(accountTradeDto.getUserNo());
        fromAccountLog.setUserName(accountTradeDto.getUserName());
        fromAccountLog.setMerNo(accountTradeDto.getMerNo());
        fromAccountLog.setMerName(accountTradeDto.getMerName());
        fromAccountLog.setSourceOrderNo(accountTradeDto.getSourceOrderNo());
        fromAccountLog.setSourceOrderType(accountTradeDto.getSourceOrderType());
        fromAccountLog.setCreateTime(new Date());
       return tbAccountLogMapper.insertSelective(fromAccountLog);
    }*/

    /**
     * 账户校验，存在则返回账户交易 不存在则进行创建
     * @param accountOperDto
     * @return
     */
    /*private AccountTradeDto accountValid(AccountOperDto accountOperDto) {
        TbAccountInfo userAccountInfo=accountInfoService.saveUserAccount(accountOperDto.getUserNo(), AccountTypeEnum.CASH_ACCOUNT);
        TbAccountInfo merAccountInfo=accountInfoService.saveMerAccount(accountOperDto.getMerNo(), AccountTypeEnum.CASH_ACCOUNT);
        AccountTradeDto accountTradeDto=new AccountTradeDto();
        if(accountOperDto.getSourceTradeType().equals(TradeTypeEnum.PAY)){
            accountTradeDto.setFromAccountNo(userAccountInfo.getAccountNo());
            accountTradeDto.setFromAccountName(userAccountInfo.getAccountName());
            accountTradeDto.setToAccountNo(merAccountInfo.getAccountNo());
            accountTradeDto.setToAccountName(merAccountInfo.getAccountName());
            accountTradeDto.setMerNo(merAccountInfo.getOwnerNo());
            accountTradeDto.setMerName(merAccountInfo.getOwnerName());
        }else if(accountOperDto.getSourceTradeType().equals(TradeTypeEnum.REFUND)){
            accountTradeDto.setToAccountNo(userAccountInfo.getAccountNo());
            accountTradeDto.setToAccountName(userAccountInfo.getAccountName());
            accountTradeDto.setFromAccountNo(merAccountInfo.getAccountNo());
            accountTradeDto.setFromAccountName(merAccountInfo.getAccountName());
            accountTradeDto.setMerNo(merAccountInfo.getOwnerNo());
            accountTradeDto.setMerName(merAccountInfo.getOwnerName());
        }
        accountTradeDto.setUserNo(userAccountInfo.getOwnerNo());
        accountTradeDto.setUserName(userAccountInfo.getOwnerName());
        accountTradeDto.setOperAmt(accountOperDto.getTradeAmt());
        accountTradeDto.setOperAction(accountOperDto.getSourceTradeType().name());
        accountTradeDto.setOperName(accountOperDto.getSourceTradeType().getName());
        accountTradeDto.setSourceOrderType(accountOperDto.getSourceTradeType().name());
        accountTradeDto.setSourceOrderNo(accountOperDto.getSourceOrderNo());
        accountTradeDto.setSourceTradeType(accountOperDto.getSourceTradeType());
        return accountTradeDto;
    }

    private AccountTradeDto accountFromValid(AccountOperDto accountOperDto) {
        TbAccountInfo userAccountInfo=accountInfoService.saveUserAccount(accountOperDto.getUserNo(), AccountTypeEnum.CASH_ACCOUNT);
        AccountTradeDto accountTradeDto=new AccountTradeDto();
        accountTradeDto.setFromAccountNo(userAccountInfo.getAccountNo());
        accountTradeDto.setFromAccountName(userAccountInfo.getAccountName());
        accountTradeDto.setUserNo(userAccountInfo.getOwnerNo());
        accountTradeDto.setUserName(userAccountInfo.getOwnerName());
        accountTradeDto.setOperAmt(accountOperDto.getTradeAmt());
        accountTradeDto.setOperAction(accountOperDto.getSourceTradeType().name());
        accountTradeDto.setOperName(accountOperDto.getSourceTradeType().getName());
        accountTradeDto.setSourceOrderType(accountOperDto.getSourceTradeType().name());
        accountTradeDto.setSourceOrderNo(accountOperDto.getSourceOrderNo());
        accountTradeDto.setSourceTradeType(accountOperDto.getSourceTradeType());
        return accountTradeDto;
    }*/

}
